﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;

namespace NDF.ConnectionLibrary
{
	/// <summary>
	/// A helper class used for sending and reading data between tcp clients.
	/// </summary>
    public static class ConnectionHelper
    {
		/// <summary>
		/// Sends a byte array over the net.
		/// </summary>
		/// <param name="client">The client to send the data to.</param>
		/// <param name="data">The data to be sent.</param>
		/// <exception cref="System.InvalidOperationException"/>
		/// <exception cref="System.ObjectDisposedException"/>
		/// <exception cref="System.ArgumentNullException"/>
		/// <exception cref="System.ArgumentOutOfRange"/>
		/// <exception cref="System.IO.IOException"/>
        public static void SendData(TcpClient client, byte[] data)
        {
            NetworkStream stream = client.GetStream();
			stream.Write(data, 0, data.Length);
        }

		/// <summary>
		/// Sends a byte array over the net.
		/// </summary>
		/// <param name="sendingClient">The stream to send the data to.</param>
		/// <param name="data">The data to be sent.</param>
		/// <exception cref="System.ObjectDisposedException"/>
		/// <exception cref="System.ArgumentNullException"/>
		/// <exception cref="System.ArgumentOutOfRange"/>
		/// <exception cref="System.IO.IOException"/>
		public static void SendData(NetworkStream stream, byte[] data)
		{
			stream.Write(data, 0, data.Length);
		}

		/// <summary>
		/// Gets a byte array from the given client.
		/// </summary>
		/// <param name="sendingClient">The client to read from.</param>
		/// <param name="bufferSize">The size of the read data.</param>
		/// <returns>The byte array read from the client.</returns>
		/// <exception cref="System.InvalidOperationException"/>
		/// <exception cref="System.ObjectDisposedException"/>
		/// <exception cref="System.ArgumentNullException"/>
		/// <exception cref="System.ArgumentOutOfRange"/>
		/// <exception cref="System.IO.IOException"/>
		public static byte[] ReadData(TcpClient client, int bufferSize)
		{
			byte[] buffer = new byte[bufferSize];
			NetworkStream stream = client.GetStream();
			stream.Read(buffer, 0, bufferSize);

			return buffer;
		}

		/// <summary>
		/// Gets a byte array from the given stream.
		/// </summary>
		/// <param name="sendingClient">The stream to read from.</param>
		/// <param name="bufferSize">The size of the read data.</param>
		/// <returns>The byte array read from the sendingClient.</returns>
		/// <exception cref="System.InvalidOperationException"/>
		/// <exception cref="System.ObjectDisposedException"/>
		/// <exception cref="System.ArgumentNullException"/>
		/// <exception cref="System.ArgumentOutOfRange"/>
		/// <exception cref="System.IO.IOException"/>
		public static byte[] ReadData(NetworkStream stream, int bufferSize)
		{
			byte[] buffer = new byte[bufferSize];
			stream.Read(buffer, 0, bufferSize);

			return buffer;
		}

		/// <summary>
		/// Gets a byte array from the given sendingClient. This method works slower than the overload with buffer size but reads all the available data.
		/// </summary>
		/// <param name="sendingClient">The sendingClient to read from.</param>
		/// <returns>The byte array read from the sendingClient.</returns>
		/// <exception cref="System.InvalidOperationException"/>
		/// <exception cref="System.ObjectDisposedException"/>
		/// <exception cref="System.ArgumentNullException"/>
		/// <exception cref="System.ArgumentOutOfRange"/>
		/// <exception cref="System.IO.IOException"/>
		public static byte[] ReadData(TcpClient client)
		{
			List<byte> buffer = new List<byte>(256);
			NetworkStream stream = client.GetStream();

			//Wait until there`s data available in the buffer,
			while (buffer.Count == 0)
			{
				//Read while you can
				while(stream.CanRead)
				{
					buffer.Add((byte)stream.ReadByte());
				}
			}
			return buffer.ToArray();
		}
	}
}
